package server;
import java.net.*;
import java.io.*;
import java.util.*;

import common.HitInformation;
import common.Shared;
import common.RobotInformation;


public class ServerHandler extends Thread
{
	private static final int
			TO_CLIENT = 0,
			TO_SERVER = 1;
	
	private Socket control[]  = new Socket[ 2 ];
	
	private int clientServerPort;

	private DataInputStream  in [] = new DataInputStream [ 2 ];
	private DataOutputStream out[] = new DataOutputStream[ 2 ];

	public ServerHandler
			( Socket control )
	{
		this.control[ TO_CLIENT ] = control;
		   
		try {
			in [ Shared.CONTROL_LINE ] =
					new DataInputStream( ( control.getInputStream() ) );
			clientServerPort = in [ Shared.CONTROL_LINE ].readInt();
			System.out.println( "Client has started listening on port "
					+ clientServerPort );
		} catch( IOException e )
		{
			Shared.error( "Could not create input control line OR READ SERVER PORT from client." );
			System.exit( 1 );
		}

		try {
			out[ Shared.CONTROL_LINE ] =
					new DataOutputStream ( control.getOutputStream() );
		} catch( IOException e ) 
		{
			Shared.error( "Could not create output control line to client." );
			System.exit( 1 );
		}
	}
	
	public InetAddress getIP()
	{
		return control[ TO_CLIENT ].getInetAddress();
	}
	
	public HitInformation request( String req )
	{
		req = "QUERY " + req;
		HitInformation result = null;
		try {
			control[ TO_SERVER ] = 
					new Socket( getIP(), 
							  	clientServerPort );
			System.out.println("query other client");	

		} catch( IOException e ){
			System.out.println( " ** ERROR: Could not query client \"" +
					getIP() + 
					"\" on port " +
					clientServerPort +
					"! **");
			return null;
		}
		
		try {
			in [ Shared.DATA_LINE ] =
				new DataInputStream	(control[ TO_SERVER ].getInputStream());
			out[ Shared.DATA_LINE ] = 
				new DataOutputStream(control[ TO_SERVER ].getOutputStream());
		} catch( IOException e ){}
		
		try {
			out[ Shared.DATA_LINE ].writeUTF( req );
			result = Shared.getHit( in [ Shared.DATA_LINE ] );
			out[ Shared.DATA_LINE ].writeUTF( Shared.QUIT );
			Shared.closeObject( control[ TO_SERVER ] );
		} catch( IOException e ){
			System.out.println( "data line error");
		}
		
		return result;
	}
	
	public void run( )
	{ 
		System.out.println
				( " -- Connected to client \"" +
				  control[ TO_CLIENT ].getInetAddress() +
				  "\" on port " +
				  control[ TO_CLIENT ].getLocalPort() + 
				  "." );
		
		String line = "";
		
		while( true )
		{
			try {
				line = in[ Shared.CONTROL_LINE ].readUTF();
			} catch( IOException e ) {
				Shared.error( "Client has unexpectedly terminated!" );
				Server.removeClient( this );
				break;
			}
			
			if( line == null )
				break;
			
			System.out.println
					( "From client (" +
					  control[ TO_CLIENT ].getLocalPort() +
					  "): \"" + 
					  line + 
					  "\"" );
			
			String parsed[] = line.split( " " );
			parsed[ 0 ] = parsed[ 0 ].toUpperCase();

			if( parsed[ Shared.COMMAND ].equals( Shared.QUIT ) )
			{
				System.out.println
						( " -- Client \"" +
						  control[ TO_CLIENT ].getInetAddress() + 
						  "\" is disconnecting from port " +
						  control[ TO_CLIENT ].getLocalPort() + 
						  "." );
				
				Shared.closeObject( control );
				Shared.closeObject( in [ Shared.CONTROL_LINE ] );
				Shared.closeObject( out[ Shared.CONTROL_LINE ] );
				
				Server.removeClient( this );
				break;
			}
/*			else if( parsed[ Shared.COMMAND ].equals( Shared.QUERY ) )
			{
				Vector< HitInformation > list;
				list = Server.request(parsed[ Shared.FILENAME ], getIP());
				try{
					Shared.sendHit(list, control[ TO_CLIENT ].getOutputStream());
				}catch(Exception e){
					System.out.println( "could not get control output stream ");
				}
			}*/
			else if( parsed[ Shared.COMMAND ].equals( Shared.ROBOT ) )
			{
				RobotInformation list;
				list = Server.requestRobotState(parsed[ Shared.FILENAME ], getIP());
				try{
					Shared.sendRobotState(list, control[ TO_CLIENT ].getOutputStream());
				}catch(Exception e){
					System.out.println( "could not get control output stream ");
				}
			}
			else if( parsed[ Shared.COMMAND ].equals( Shared.QUERY ) )
			{
				Server.moveRobot(parsed[ Shared.FILENAME ]);
				Vector< HitInformation > list = new Vector<HitInformation>(0);
				try{
					Shared.sendHit(list, control[ TO_CLIENT ].getOutputStream());
				}catch(Exception e){
					System.out.println( "could not get control output stream ");
				}
			}
		}
	}
}
